package v3

import (
	"bytes"
	"encoding/json"
	"io"
	"reflect"
	"strconv"
	"sync"
)

// ------------ Api v3 - payData(支付数据处理) -----------------//

var BufPool = sync.Pool{
	New: func() interface{} {
		return bytes.NewBuffer(make([]byte, 0, 4<<10)) //4KB
	},
}

type PayData struct {
	Data map[string]interface{}
}

// 初始化
func NewPayData() *PayData {
	return &PayData{Data: make(map[string]interface{})}
}

// 判断 map的 key值 是否存在
func (pd *PayData) IsSet(key string) bool {
	_, ok := pd.Data[key]
	return ok
}

// 设置map值
func (pd *PayData) Set(key string, val interface{}) {
	vKind := reflect.ValueOf(val).Kind()
	switch vKind {
	case reflect.String:
		pd.Data[key] = val.(string)
	case reflect.Int:
		pd.Data[key] = strconv.Itoa(val.(int))
	case reflect.Int64:
		pd.Data[key] = strconv.FormatInt(val.(int64), 10)
	case reflect.Float32:
		pd.Data[key] = strconv.FormatFloat(float64(val.(float32)), 'f', -1, 32)
	case reflect.Float64:
		pd.Data[key] = strconv.FormatFloat(val.(float64), 'f', -1, 64)
	case reflect.Ptr:
		pd.Data[key] = val
	case reflect.Struct:
		pd.Data[key] = val
	case reflect.Map:
		pd.Data[key] = val
	case reflect.Slice:
		pd.Data[key] = val
	default:
		pd.Data[key] = ""
	}
}

// 获取map值
func (pd *PayData) Get(key string) string {
	val, ok := pd.Data[key]
	if !ok {
		return ""
	}
	_, oks := val.(string)
	if oks {
		return val.(string)
	} else {
		b, err := json.Marshal(val)
		if err != nil {
			return ""
		}
		str := string(b)
		if str == "null" {
			return ""
		}
		return str
	}
}

// 转换成json
func (pd *PayData) ToJson() string {
	b, err := json.Marshal(pd.Data)
	if err != nil {
		return ""
	} else {
		return string(b)
	}
}

// json 转 map
func (pd *PayData) FromJson(r io.Reader) error {
	buf := BufPool.Get().(*bytes.Buffer)
	buf.Reset()
	defer BufPool.Put(buf)

	_, err := buf.ReadFrom(r)
	if err != nil {
		return err
	}

	var jsonTemplate interface{}
	err = json.Unmarshal(buf.Bytes(), &jsonTemplate)
	if err != nil {
		return err
	}

	pd.Data = jsonTemplate.(map[string]interface{})

	return nil
}

// json字符串 转 map
func (pd *PayData) FromJsonStr(s string) error {
	var jsonTemplate interface{}
	err := json.Unmarshal([]byte(s), &jsonTemplate)
	if err != nil {
		return err
	}
	pd.Data = jsonTemplate.(map[string]interface{})

	return nil
}
